home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 25 / Cream of the Crop 25.iso / program / fpk65_66.zip / SOURCE / RTL / DOS / GO32.PP < prev    next >
Text File  |  1996-11-07  |  17KB  |  663 lines

  1. {****************************************************************************
  2.  
  3.                       Copyright (c) 1996 by Florian Klaempfl
  4.  
  5.  ****************************************************************************}
  6.  
  7. {
  8.   this unit is part of the FPKPascal run time library
  9.   and implements some stuff for protected mode programming
  10.  
  11.   History:
  12.        6th november 1996:
  13.          + dosmem* implemented
  14. }
  15.  
  16. unit go32;
  17.  
  18.   interface
  19.  
  20.     const
  21.        { contants for the run modes returned by get_run_mode }
  22.        rm_unknown = 0;
  23.        { raw (without HIMEM) }
  24.        rm_raw = 1;
  25.        { XMS (for example with HIMEM, without EMM386) }
  26.        rm_xms = 2;
  27.        { VCPI (for example HIMEM and EMM386) }
  28.        rm_vcpi = 3;
  29.        { DPMI (for example DOS box or 386Max) }
  30.        rm_dpmi = 4;
  31.   
  32.     type
  33.        tmeminfo = record
  34.           available_memory : longint;
  35.           available_pages : longint;
  36.           available_lockable_pages : longint;
  37.           linear_space : longint;
  38.           unlocked_pages : longint;
  39.           available_physical_pages : longint;
  40.           total_physical_pages : longint;
  41.           free_linear_space : longint;
  42.           max_pages_in_paging_file : longint;
  43.           reserved : array[0..2] of longint;
  44.        end;
  45.               
  46.        tseginfo = record
  47.           offset : pointer;
  48.           segment : word;
  49.        end;
  50.  
  51.        trealregs=record
  52.           realedi,realesi,realebp,realres,
  53.           realebx,realedx,realecx,realeax : longint;
  54.  
  55.           realflags,
  56.           reales,realds,realfs,realgs,
  57.           realip,realcs,realsp,realss : word;
  58.        end;
  59.  
  60.     { this works only with real DPMI }
  61.     function allocate_ldt_descriptors(count : word) : word;
  62.     procedure free_ldt_descriptor(d : word);
  63.     function segment_to_descriptor(seg : word) : word;
  64.     function get_next_selector_increment_value : word;
  65.     function get_segment_base_address(d : word) : longint;
  66.     procedure set_segment_base_address(d : word;s : longint);
  67.     procedure set_segment_limit(d : word;s : longint);
  68.     function create_code_segment_alias_descriptor(seg : word) : word;
  69.     function get_linear_addr(phys_addr : longint;size : longint) : longint;
  70.  
  71.     { is needed for functions which need a real mode buffer }
  72.     function  global_dos_alloc(bytes : longint) : longint;
  73.     procedure global_dos_free(selector : word);
  74.     
  75.     var
  76.        { selector for the DOS memory (only usable if in DPMI mode) }
  77.        dosmemselector : word;
  78.  
  79.     { this procedure copies data where the source and destination }
  80.     { are specified by 48 bit pointers                            }
  81.     { Note: the procedure checks only for overlapping if          }
  82.     { source selector=destination selector                        }
  83.     procedure seg_move(sseg : word;source : longint;dseg : word;dest : longint;count : longint);
  84.  
  85.     { fills a memory area specified by a 48 bit pointer with c }
  86.     procedure seg_fillchar(seg : word;ofs : longint;count : longint;c : char);
  87.     procedure seg_fillword(seg : word;ofs : longint;count : longint;w : word);
  88.     
  89.     {************************************}
  90.     { this works with all PM interfaces: }
  91.     {************************************}
  92.  
  93.     procedure get_meminfo(var meminfo : tmeminfo);
  94.     procedure get_pm_interrupt(vector : byte;var intaddr : tseginfo);
  95.     procedure set_pm_interrupt(vector : byte;const intaddr : tseginfo);
  96.     function get_cs : word;
  97.     function get_ds : word;
  98.     function get_ss : word;
  99.  
  100.     { disables and enables interrupts }
  101.     procedure disable;
  102.     procedure enable;
  103.  
  104.     function inportb(port : word) : byte;
  105.     function inportw(port : word) : word;
  106.     function inportl(port : word) : longint;
  107.  
  108.     procedure outportb(port : word;data : byte);
  109.     procedure outportw(port : word;data : word);
  110.     procedure outportl(port : word;data : longint);
  111.     function get_run_mode : word;
  112.  
  113.     procedure realintr(intnr : word;var regs : trealregs);
  114.  
  115.     var
  116.        { this procedures are assigned to the procedure which are needed }
  117.        { for the current mode to access DOS memory                      }
  118.        { It's strongly recommended to use this procedures!              }
  119.        dosmemput : procedure(seg : word;ofs : word;var data;count : longint);
  120.        dosmemget : procedure(seg : word;ofs : word;var data;count : longint);
  121.        dosmemmove : procedure(sseg,sofs,dseg,dofs : word;count : longint);
  122.        dosmemfillchar : procedure(seg,ofs : word;count : longint;c : char);
  123.        dosmemfillword : procedure(seg,ofs : word;count : longint;w : word);
  124.  
  125.   implementation
  126.  
  127.     { the following procedures copy from and to DOS memory without DPMI }
  128.     procedure raw_dosmemput(seg : word;ofs : word;var data;count : longint);
  129.  
  130.       begin
  131.          move(data,pointer($e0000000+seg*16+ofs)^,count);
  132.       end;
  133.  
  134.     procedure raw_dosmemget(seg : word;ofs : word;var data;count : longint);
  135.  
  136.       begin
  137.          move(pointer($e0000000+seg*16+ofs)^,data,count);
  138.       end;
  139.  
  140.     procedure raw_dosmemmove(sseg,sofs,dseg,dofs : word;count : longint);
  141.  
  142.       begin
  143.          move(pointer($e0000000+sseg*16+sofs)^,pointer($e0000000+dseg*16+dofs)^,count);
  144.       end;
  145.       
  146.     procedure raw_dosmemfillchar(seg,ofs : word;count : longint;c : char);
  147.     
  148.       begin
  149.          fillchar(pointer($e0000000+seg*16+ofs)^,count,c);
  150.       end;
  151.       
  152.     procedure raw_dosmemfillword(seg,ofs : word;count : longint;w : word);
  153.     
  154.       begin
  155.          fillword(pointer($e0000000+seg*16+ofs)^,count,w);
  156.       end;
  157.       
  158.     { the following procedures copy from and to DOS memory using DPMI }
  159.     procedure dpmi_dosmemput(seg : word;ofs : word;var data;count : longint);
  160.  
  161.       begin
  162.          seg_move(get_ds,longint(@data),dosmemselector,seg*16+ofs,count);
  163.       end;
  164.  
  165.     procedure dpmi_dosmemget(seg : word;ofs : word;var data;count : longint);
  166.  
  167.       begin
  168.          seg_move(dosmemselector,seg*16+ofs,get_ds,longint(@data),count);
  169.       end;
  170.  
  171.     procedure dpmi_dosmemmove(sseg,sofs,dseg,dofs : word;count : longint);
  172.  
  173.       begin
  174.          seg_move(dosmemselector,sseg*16+sofs,dosmemselector,dseg*16+dofs,count);
  175.       end;
  176.  
  177.     procedure dpmi_dosmemfillchar(seg,ofs : word;count : longint;c : char);
  178.     
  179.       begin
  180.          seg_fillchar(dosmemselector,seg*16+ofs,count,c);
  181.       end;
  182.       
  183.     procedure dpmi_dosmemfillword(seg,ofs : word;count : longint;w : word);
  184.     
  185.       begin
  186.          seg_fillword(dosmemselector,seg*16+ofs,count,w);
  187.       end;
  188.       
  189.     function global_dos_alloc(bytes : longint) : longint;
  190.  
  191.       begin
  192.          asm
  193.             movl bytes,%ebx
  194.             orl  $0x10,%ebx             // round up
  195.             shrl $0x4,%ebx              // convert to Paragraphs
  196.             movw $0x100,%ax             // function 0x100
  197.             int  $0x31
  198.             shll $0x10,%eax             // return Segment in hi(Result)
  199.             movw %dx,%ax                // return Selector in lo(Result)
  200.             movl %eax,__result
  201.          end;
  202.       end;
  203.  
  204.     procedure  global_dos_free(selector : word);
  205.  
  206.       begin
  207.          asm
  208.             movw Selector,%dx
  209.             movw $0x101,%ax
  210.             int  $0x31
  211.          end;
  212.       end;
  213.  
  214.     procedure realintr(intnr : word;var regs : trealregs);
  215.  
  216.       begin
  217.          asm
  218.             movw  intnr,%bx
  219.             xorl  %ecx,%ecx
  220.             movl  regs,%edi
  221.  
  222.             // es is always equal ds
  223.             movw  $0x300,%ax
  224.             int   $0x31
  225.          end;
  226.       end;
  227.  
  228.     procedure seg_fillchar(seg : word;ofs : longint;count : longint;c : char);
  229.  
  230.       begin
  231.          asm
  232.             movl ofs,%edi
  233.             movl count,%ecx
  234.             movb c,%dl
  235.             { load es with selector }
  236.             pushw %es
  237.             movw seg,%ax
  238.             movw %ax,%es
  239.             { fill eax with duplicated c }
  240.             { so we can use stosl        }
  241.             movb %dl,%dh
  242.             movw %dx,%ax
  243.             shll $16,%eax
  244.             movw %dx,%ax
  245.             movl %ecx,%edx
  246.             shrl $2,%ecx
  247.             cld
  248.             rep
  249.             stosl
  250.             movl %edx,%ecx
  251.             andl $3,%ecx
  252.             rep
  253.             stosb
  254.             popw %es
  255.          end ['EAX','ECX','EDX','EDI'];
  256.       end;
  257.  
  258.     procedure seg_fillword(seg : word;ofs : longint;count : longint;w : word);
  259.  
  260.       begin
  261.          asm
  262.             movl ofs,%edi
  263.             movl count,%ecx
  264.             movw w,%dx
  265.             { load segment }
  266.             pushw %es
  267.             movw seg,%ax
  268.             movw %ax,%es
  269.             { fill eax }
  270.             movw %dx,%ax
  271.             shll $16,%eax
  272.             movw %dx,%ax
  273.             movl %ecx,%edx
  274.             shrl $1,%ecx
  275.             cld
  276.             rep
  277.             stosl
  278.             movl %edx,%ecx
  279.             andl $1,%ecx
  280.             rep
  281.             stosw
  282.             popw %es
  283.          end ['EAX','ECX','EDX','EDI'];
  284.       end;
  285.  
  286.     procedure seg_move(sseg : word;source : longint;dseg : word;dest : longint;count : longint);
  287.  
  288.       begin
  289.          if count=0 then
  290.            exit;
  291.          if (sseg<>dseg) or ((sseg=dseg) and (source>dest)) then
  292.            asm
  293.               pushw %es
  294.               pushw %ds
  295.               cld
  296.               movl count,%ecx
  297.               movl source,%esi
  298.               movl dest,%edi
  299.               movw dseg,%ax
  300.               movw %ax,%es
  301.               movw sseg,%ax
  302.               movw %ax,%ds
  303.               movl %ecx,%eax
  304.               shrl $2,%ecx
  305.               rep
  306.               movsl
  307.               movl %eax,%ecx
  308.               andl $3,%ecx
  309.               rep
  310.               movsb
  311.               popw %ds
  312.               popw %es
  313.            end ['ESI','EDI','ECX','EAX']
  314.          else if (source<dest) then
  315.            { copy backward for overlapping }
  316.            asm
  317.               pushw %es
  318.               pushw %ds
  319.               std              
  320.               movl count,%ecx
  321.               movl source,%esi
  322.               movl dest,%edi
  323.               movw dseg,%ax
  324.               movw %ax,%es
  325.               movw sseg,%ax
  326.               movw %ax,%ds
  327.               addl %ecx,%esi
  328.               addl %ecx,%edi
  329.               movl %ecx,%eax
  330.               andl $3,%ecx
  331.               orl %ecx,%ecx
  332.               jz LSEG_MOVE1
  333.               
  334.               { calculate esi and edi}
  335.               decl %esi
  336.               decl %edi
  337.               rep
  338.               movsb
  339.               incl %esi
  340.               incl %edi
  341.            LSEG_MOVE1:
  342.               subl $4,%esi
  343.               subl $4,%edi
  344.               movl %eax,%ecx
  345.               shrl $2,%ecx
  346.               rep
  347.               movsl
  348.               cld
  349.               popw %ds
  350.               popw %es
  351.            end ['ESI','EDI','ECX'];
  352.       end;
  353.  
  354.     procedure outportb(port : word;data : byte);
  355.  
  356.       begin
  357.          asm
  358.             movw port,%dx
  359.             movb data,%al
  360.             outb %al,%dx
  361.          end ['EAX','EDX'];
  362.       end;
  363.  
  364.     procedure outportw(port : word;data : word);
  365.  
  366.       begin
  367.          asm
  368.             movw port,%dx
  369.             movw data,%ax
  370.             outw %ax,%dx
  371.          end ['EAX','EDX'];
  372.       end;
  373.  
  374.     procedure outportl(port : word;data : longint);
  375.  
  376.       begin
  377.          asm
  378.             movw port,%dx
  379.             movl data,%eax
  380.             outl %eax,%dx
  381.          end ['EAX','EDX'];
  382.       end;
  383.  
  384.     function inportb(port : word) : byte;
  385.  
  386.       begin
  387.          asm
  388.             movw port,%dx
  389.             inb %dx,%al
  390.             movb %al,__RESULT
  391.          end ['EAX','EDX'];
  392.       end;
  393.  
  394.     function inportw(port : word) : word;
  395.  
  396.       begin
  397.          asm
  398.             movw port,%dx
  399.             inw %dx,%ax
  400.             movw %ax,__RESULT
  401.          end ['EAX','EDX'];
  402.       end;
  403.  
  404.     function inportl(port : word) : longint;
  405.  
  406.       begin
  407.          asm
  408.             movw port,%dx
  409.             inl %dx,%eax
  410.             movl %eax,__RESULT
  411.          end ['EAX','EDX'];
  412.       end;
  413.  
  414.     function get_cs : word;
  415.     
  416.       begin
  417.          asm
  418.             movw %cs,%ax
  419.             movw %ax,__RESULT;
  420.          end;
  421.       end; 
  422.    
  423.     function get_ss : word;
  424.     
  425.       begin
  426.          asm
  427.             movw %ss,%ax
  428.             movw %ax,__RESULT;
  429.          end;
  430.       end; 
  431.    
  432.     function get_ds : word;
  433.     
  434.       begin
  435.          asm
  436.             movw %ds,%ax
  437.             movw %ax,__RESULT;
  438.          end;
  439.       end; 
  440.    
  441.     procedure set_pm_interrupt(vector : byte;const intaddr : tseginfo);
  442.     
  443.       begin
  444.          asm
  445.             movl intaddr,%eax
  446.             movl (%eax),%edx
  447.             movw 4(%eax),%cx
  448.             movw $0x205,%ax
  449.             movb vector,%bl
  450.             int $0x31
  451.          end;
  452.       end;
  453.  
  454.     procedure get_pm_interrupt(vector : byte;var intaddr : tseginfo);
  455.     
  456.       begin
  457.          asm
  458.             movb vector,%bl
  459.             movw $0x204,%ax        
  460.             int $0x31
  461.             movl intaddr,%eax
  462.             movl %edx,(%eax)
  463.             movw %cx,4(%eax)
  464.          end;
  465.       end;
  466.       
  467.     function allocate_ldt_descriptors(count : word) : word;
  468.     
  469.       begin
  470.          asm
  471.             movw count,%cx
  472.             movw $0,%ax
  473.             int $0x31
  474.             movw %ax,__RESULT
  475.          end;
  476.       end;
  477.     
  478.     procedure free_ldt_descriptor(d : word);
  479.     
  480.       begin
  481.          asm
  482.              movw d,%bx
  483.              movw $1,%ax
  484.              int $0x31
  485.       end;
  486.        end;
  487.  
  488.     function segment_to_descriptor(seg : word) : word;
  489.     
  490.       begin
  491.          asm
  492.              movw seg,%bx
  493.              movw $2,%ax
  494.              int $0x31
  495.              movw %ax,__RESULT
  496.       end;
  497.        end;
  498.     
  499.     function get_next_selector_increment_value : word;
  500.     
  501.       begin
  502.          asm
  503.              movw $3,%ax
  504.              int $0x31
  505.              movw %ax,__RESULT
  506.       end;
  507.        end;
  508.  
  509.     function get_segment_base_address(d : word) : longint;
  510.  
  511.       begin
  512.          asm
  513.             movw d,%bx
  514.             movw $6,%ax
  515.             int $0x31
  516.             xorl %eax,%eax
  517.             movw %dx,%ax
  518.             shll $16,%ecx
  519.             orl %ecx,%eax
  520.             movl %eax,__RESULT
  521.          end;
  522.       end;
  523.  
  524.     procedure set_segment_base_address(d : word;s : longint);
  525.  
  526.       begin
  527.          asm
  528.             movw d,%bx
  529.             leal s,%eax
  530.             movw (%eax),%dx
  531.             movw 2(%eax),%cx
  532.             movw $7,%ax
  533.             int $0x31
  534.          end;
  535.       end;
  536.  
  537.     procedure set_segment_limit(d : word;s : longint);
  538.  
  539.       begin
  540.          asm
  541.             movw d,%bx
  542.             leal s,%eax
  543.             movw (%eax),%dx
  544.             movw 2(%eax),%cx
  545.             movw $8,%ax
  546.             int $0x31
  547.          end;
  548.       end;
  549.  
  550.     function create_code_segment_alias_descriptor(seg : word) : word;
  551.     
  552.       begin
  553.          asm
  554.              movw seg,%bx
  555.              movw $0xa,%ax
  556.              int $0x31
  557.              movw %ax,__RESULT
  558.       end;
  559.        end;
  560.        
  561.     procedure get_meminfo(var meminfo : tmeminfo);
  562.     
  563.       begin
  564.          asm
  565.             movl meminfo,%edi
  566.             movw $0x500,%ax
  567.             int $0x31
  568.          end;
  569.       end;   
  570.       
  571.     function get_linear_addr(phys_addr : longint;size : longint) : longint;
  572.     
  573.       begin
  574.          asm
  575.             movl phys_addr,%ebx
  576.             movl %ebx,%ecx
  577.             shrl $16,%ebx
  578.             movl phys_addr,%esi
  579.             movl %esi,%edi
  580.             shrl $16,%esi
  581.             movw $0x800,%ax
  582.             int $0x31
  583.             shll $16,%ebx
  584.             movw %cx,%bx
  585.             movl %ebx,__RESULT
  586.          end;
  587.       end;
  588.  
  589.     procedure disable;
  590.  
  591.       begin
  592.          asm
  593.             cli;
  594.          end;
  595.       end;
  596.  
  597.     procedure enable;
  598.  
  599.       begin
  600.          asm
  601.             sti;
  602.          end;
  603.       end;
  604.  
  605.     function get_run_mode : word;
  606.  
  607.       begin
  608.          asm
  609.             movw _run_mode,%ax
  610.             movw %ax,__RESULT
  611.          end ['EAX'];
  612.       end;
  613. {
  614. typedef struct {
  615.   unsigned long handle;            /* 0, 2 */
  616.   unsigned long size;     /* or count */    /* 4, 6 */
  617.   unsigned long address;        /* 8, 10 */
  618. } __dpmi_meminfo;
  619.     procedure map_device_in_memory_block(const meminfo : tmeminfo;
  620.       phys_addr : longint);
  621.  
  622.       begin
  623.          asm
  624.         movl meminfo,%eax
  625.             movl (%eax),%esi
  626.         movl 4(%eax),%ecx
  627.         movl 8(%eax),%ebx
  628.         movl phys_addr,%edx
  629.             movw $0x508,%ax
  630.             int $0x31
  631.          end;
  632.       end;
  633. }
  634.  
  635.     function get_core_selector : word;
  636.     
  637.       begin
  638.          asm
  639.             movw _core_selector,%ax
  640.             movw %ax,__RESULT
  641.          end;
  642.       end; 
  643.  
  644. begin
  645.    if get_run_mode=rm_dpmi then
  646.      begin
  647.         dosmemget:=@dpmi_dosmemget;
  648.         dosmemput:=@dpmi_dosmemput;
  649.         dosmemmove:=@dpmi_dosmemmove;
  650.         dosmemfillchar:=@dpmi_dosmemfillchar;
  651.         dosmemfillword:=@dpmi_dosmemfillword;
  652.         dosmemselector:=get_core_selector;
  653.      end
  654.    else
  655.      begin
  656.         dosmemget:=@raw_dosmemget;
  657.         dosmemput:=@raw_dosmemput;
  658.         dosmemmove:=@raw_dosmemmove;
  659.         dosmemfillchar:=@raw_dosmemfillchar;
  660.         dosmemfillword:=@raw_dosmemfillword;
  661.      end;
  662. end.
  663.